/**
 * Copyright (c) 2016-2020 https://github.com/zhaohuatai
 *
 * contact 824069438@qq.com
 *  
 */
package org.zfes.snowy.auth.shiro.filter.sso;

import java.io.PrintWriter;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.session.Session;
import org.apache.shiro.web.filter.PathMatchingFilter;
import org.apache.shiro.web.util.WebUtils;
import org.zfes.snowy.auth.AuthConsts;
import org.zfes.snowy.auth.shiro.util.SSOVerifyEncyptKeyUtil;
import org.zfes.snowy.core.consts.FrameConst;
import org.zfes.snowy.core.data.JSONMSG;
import org.zfes.snowy.core.util.Base58Util;
import org.zfes.snowy.core.util.CookieUtil;
import org.zfes.snowy.core.util.ZStrUtil;
import org.zfes.snowy.core.util.ZWebUtil;
import org.zfes.snowy.core.util.encypt.AESUtil;
import org.zfes.snowy.core.util.encypt.RSAUtil;

/**
 * /api/auth/sso/client/sync.so<br>
 * 
 *  
 * @author zhaoht
 *
 */
public class SSOSyncClientFilter extends PathMatchingFilter implements SSOSyncFilter{
	
	private String ssoClientSyncPath=AuthConsts.SSO.ssoClientSyncPath;
	
	@Override
	protected boolean onPreHandle(ServletRequest request, ServletResponse response, Object mappedValue)throws Exception {
	    	HttpServletResponse httpResponse =(HttpServletResponse)response;
	    	HttpServletRequest httpRequest=(HttpServletRequest) request ;
	    	Session session =  SecurityUtils.getSubject().getSession();
	    	if(pathsMatch(ssoClientSyncPath,httpRequest)){
		    	//接收参数
			    String ssoToken = WebUtils.getCleanParam(request, AuthConsts.SSO.ssoTokenParam);//
			    String ssoSign = WebUtils.getCleanParam(request, AuthConsts.SSO.ssoSignParam);//
			    //校验参数
			    if(ZStrUtil.hasNoText(ssoToken)||ZStrUtil.hasNoText(ssoToken)){
		   			ZWebUtil.respJSON(httpResponse, new JSONMSG(FrameConst.SC.SC_500, "数字签名参数错误")); 
		   			session.stop();   
		   			return false;
			    }
			    if(ZStrUtil.hasNoText(ssoSign)||ZStrUtil.hasNoText(ssoSign)){
		   			ZWebUtil.respJSON(httpResponse, new JSONMSG(FrameConst.SC.SC_500, "数字签名参数错误")); 
		   			session.stop();
		   			return false;
			    }
			    String aesPublicKey=SSOVerifyEncyptKeyUtil.readSSOAesPublicKey();
			    ssoToken=Base58Util.decodeFromBase58(ssoToken);
			    ssoSign=Base58Util.decodeFromBase58(ssoSign);
			    
			    //decode from AES
			    ssoToken=AESUtil.decrypt(ssoToken, aesPublicKey);
			    ssoSign=AESUtil.decrypt(ssoSign, aesPublicKey);
			    
			    //数字签名校验
			    boolean status=RSAUtil.verify(ssoToken.getBytes(), SSOVerifyEncyptKeyUtil.readSSOSignPublicKey(), ssoSign);//签名验证
		   		if(!status){
		   			ZWebUtil.respJSON(httpResponse, new JSONMSG(FrameConst.SC.SC_500, "数字签名校验错误")); 
		   			session.stop();
		   			return false;
		   		}
		   		//解析sesisonid
		   		String sessionId=ZStrUtil.substringBefore(ssoToken, "#");//解析出ssoCenter的sessionid
		   		if(!session.getId().toString().equals(sessionId)){
		   			session.stop();
		   			System.out.println("session stoped");
		   		}
		   		System.out.println("SSOSyncClientFilter-session.getId()|| "+session.getId());
		   		System.out.println("SSOSyncClientFilter-sessionid|| "+sessionId);
		   		// 写cookies
		   		CookieUtil.setSessionCookie(WebUtils.toHttp(response),AuthConsts.COOKIES.authSid,sessionId,"/",true) ;
		   		CookieUtil.setSessionCookie(WebUtils.toHttp(response),AuthConsts.COOKIES.syncsid,"true","/",false);
					
				//CookieUtil.deleteAllCookie( httpRequest, httpResponse , AuthConsts.COOKIES.authSid, session.getId().toString());
				PrintWriter out = httpResponse.getWriter();
				String callback = WebUtils.getCleanParam(request, "jsonpCallback");
				callback=ZStrUtil.hasNoText(callback)?"jsonpCallback":callback;
				out.println(callback+"({\"statusCode\":\"200\"})");
			    out.flush();  
			    out.close();
			    return false;
	    	}
			return true;
	 
	}

	public String getSsoClientSyncPath() {
		return ssoClientSyncPath;
	}

	public void setSsoClientSyncPath(String ssoClientSyncPath) {
		this.ssoClientSyncPath = ssoClientSyncPath;
	}
	
}
